// -*- c++ -*-

#pragma once

#include <litc.h>
#include <type_traits>

namespace std {
  template <class T>
  T&&
  forward(typename remove_reference<T>::type& t)
  {
    return static_cast<T&&>(t);
  }

  template <class T>
  T&&
  forward(typename remove_reference<T>::type&& t)
  {
    return static_cast<T&&>(t);
  }

  template<class T>
  typename remove_reference<T>::type&&
  move(T&& a)
  {
    return static_cast<typename remove_reference<T>::type&&>(a);
  }

  template<class T>
  void
  swap(T& a, T& b)
  {
    T tmp = move(a);
    a = move(b);
    b = move(tmp);
  }

  template<class T, size_t N>
  void
  swap(T (&a)[N], T (&b)[N])
  {
    for (size_t n = 0; n < N; n++)
      swap(a[n], b[n]);
  }

  template<class A, class B>
  struct pair {
    typedef A first_type;
    typedef B second_type;

    A first;
    B second;

    pair(const pair&) = default;
    pair(pair&&) = default;
    constexpr pair() : first(), second() {}
    pair(const A &a, const B &b) : first(a), second(b) {}

    bool operator==(const pair<A, B> &other) const {
      return first == other.first && second == other.second;
    }
  };

  template<class A, class B>
  pair<A, B>
  make_pair(const A &a, const B &b)
  {
    return pair<A, B>(a, b);
  }
}
